home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / gimpbrush.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-01  |  9.4 KB  |  411 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <glib.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25.  
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #ifdef HAVE_UNISTD_H
  29. #include <unistd.h>
  30. #endif
  31. #include <fcntl.h>
  32.  
  33. #ifdef G_OS_WIN32
  34. #include <io.h>
  35. #endif
  36.  
  37. #ifndef _O_BINARY
  38. #define _O_BINARY 0
  39. #endif
  40.  
  41. #include <gtk/gtk.h>
  42.  
  43.  
  44. #include <stdio.h>
  45.  
  46. #include "apptypes.h"
  47.  
  48. #include "libgimp/gimpvector.h"
  49.  
  50. #include "brush_header.h"
  51. #include "pattern_header.h"
  52. #include "gimpbrush.h"
  53. #include "gimpbrushlist.h"
  54.  
  55. #include "gimpsignal.h"
  56. #include "gimprc.h"
  57.  
  58. #include "paint_core.h"
  59. #include "temp_buf.h"
  60.  
  61. #include "libgimp/gimpintl.h"
  62.  
  63. enum
  64. {
  65.   DIRTY,
  66.   RENAME,
  67.   LAST_SIGNAL
  68. };
  69.  
  70. static GimpBrush * gimp_brush_select_brush     (PaintCore *paint_core);
  71. static gboolean    gimp_brush_want_null_motion (PaintCore *paint_core);
  72.  
  73. static guint gimp_brush_signals[LAST_SIGNAL];
  74.  
  75. static GimpObjectClass *parent_class;
  76.  
  77. static void
  78. gimp_brush_destroy (GtkObject *object)
  79. {
  80.   GimpBrush *brush = GIMP_BRUSH (object);
  81.  
  82.   g_free (brush->filename);
  83.   g_free (brush->name);
  84.  
  85.   if (brush->mask)
  86.     temp_buf_free (brush->mask);
  87.  
  88.   if (brush->pixmap)
  89.     temp_buf_free (brush->pixmap);
  90.  
  91.   if (GTK_OBJECT_CLASS (parent_class)->destroy)
  92.     GTK_OBJECT_CLASS (parent_class)->destroy (object);
  93. }
  94.  
  95. static void
  96. gimp_brush_class_init (GimpBrushClass *klass)
  97. {
  98.   GtkObjectClass *object_class;
  99.   GtkType         type;
  100.   
  101.   object_class = GTK_OBJECT_CLASS (klass);
  102.  
  103.   parent_class = gtk_type_class (gimp_object_get_type ());
  104.   
  105.   type = object_class->type;
  106.  
  107.   object_class->destroy = gimp_brush_destroy;
  108.  
  109.   klass->select_brush = gimp_brush_select_brush;
  110.   klass->want_null_motion = gimp_brush_want_null_motion;
  111.  
  112.   gimp_brush_signals[DIRTY] =
  113.     gimp_signal_new ("dirty",  GTK_RUN_FIRST, type, 0, gimp_sigtype_void);
  114.  
  115.   gimp_brush_signals[RENAME] =
  116.     gimp_signal_new ("rename", GTK_RUN_FIRST, type, 0, gimp_sigtype_void);
  117.  
  118.   gtk_object_class_add_signals (object_class, gimp_brush_signals, LAST_SIGNAL);
  119. }
  120.  
  121. void
  122. gimp_brush_init (GimpBrush *brush)
  123. {
  124.   brush->filename  = NULL;
  125.   brush->name      = NULL;
  126.  
  127.   brush->spacing   = 20;
  128.   brush->x_axis.x  = 15.0;
  129.   brush->x_axis.y  =  0.0;
  130.   brush->y_axis.x  =  0.0;
  131.   brush->y_axis.y  = 15.0;
  132.  
  133.   brush->mask      = NULL;
  134.   brush->pixmap    = NULL;
  135. }
  136.  
  137.  
  138. GtkType
  139. gimp_brush_get_type (void)
  140. {
  141.   static GtkType type = 0;
  142.  
  143.   if (!type)
  144.     {
  145.       static const GtkTypeInfo info =
  146.       {
  147.         "GimpBrush",
  148.         sizeof (GimpBrush),
  149.         sizeof (GimpBrushClass),
  150.         (GtkClassInitFunc) gimp_brush_class_init,
  151.         (GtkObjectInitFunc) gimp_brush_init,
  152.         /* reserved_1 */ NULL,
  153.         /* reserved_2 */ NULL,
  154.         (GtkClassInitFunc) NULL
  155.       };
  156.  
  157.     type = gtk_type_unique (gimp_object_get_type (), &info);
  158.   }
  159.   return type;
  160. }
  161.  
  162. GimpBrush *
  163. gimp_brush_load (gchar *filename)
  164. {
  165.   GimpBrush *brush;
  166.   gint       fd;
  167.  
  168.   g_return_val_if_fail (filename != NULL, NULL);
  169.  
  170.   fd = open (filename, O_RDONLY | _O_BINARY);
  171.   if (fd == -1) 
  172.     return NULL;
  173.  
  174.   brush = gimp_brush_load_brush (fd, filename);
  175.  
  176.   close (fd);
  177.  
  178.   if (!brush)
  179.     return NULL;
  180.  
  181.   brush->filename = g_strdup (filename);
  182.  
  183.   /*  Swap the brush to disk (if we're being stingy with memory) */
  184.   if (stingy_memory_use)
  185.     {
  186.       temp_buf_swap (brush->mask);
  187.       if (brush->pixmap)
  188.         temp_buf_swap (brush->pixmap);
  189.     }
  190.  
  191.   return brush;
  192. }
  193.  
  194. static GimpBrush *
  195. gimp_brush_select_brush (PaintCore *paint_core)
  196. {
  197.   return paint_core->brush;
  198. }
  199.  
  200. static gboolean
  201. gimp_brush_want_null_motion (PaintCore *paint_core)
  202. {
  203.   return TRUE;
  204. }
  205.  
  206. TempBuf *
  207. gimp_brush_get_mask (GimpBrush *brush)
  208. {
  209.   g_return_val_if_fail (brush != NULL, NULL);
  210.   g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
  211.  
  212.   return brush->mask;
  213. }
  214.  
  215. TempBuf *
  216. gimp_brush_get_pixmap (GimpBrush *brush)
  217. {
  218.   g_return_val_if_fail (brush != NULL, NULL);
  219.   g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
  220.  
  221.   return brush->pixmap;
  222. }
  223.  
  224. gchar *
  225. gimp_brush_get_name (GimpBrush *brush)
  226. {
  227.   g_return_val_if_fail (brush != NULL, NULL);
  228.   g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
  229.  
  230.   return brush->name;
  231. }
  232.  
  233. void
  234. gimp_brush_set_name (GimpBrush *brush, 
  235.              gchar     *name)
  236. {
  237.   g_return_if_fail (brush != NULL);
  238.   g_return_if_fail (GIMP_IS_BRUSH (brush));
  239.  
  240.   if (strcmp (brush->name, name) == 0)
  241.     return;
  242.  
  243.   if (brush->name)
  244.     g_free (brush->name);
  245.   brush->name = g_strdup (name);
  246.  
  247.   gtk_signal_emit (GTK_OBJECT (brush), gimp_brush_signals[RENAME]);
  248. }
  249.  
  250. gint
  251. gimp_brush_get_spacing (GimpBrush *brush)
  252. {
  253.   g_return_val_if_fail (brush != NULL, 0);
  254.   g_return_val_if_fail (GIMP_IS_BRUSH (brush), 0);
  255.  
  256.   return brush->spacing;
  257. }
  258.  
  259. void
  260. gimp_brush_set_spacing (GimpBrush *brush,
  261.             gint       spacing)
  262. {
  263.   g_return_if_fail (brush != NULL);
  264.   g_return_if_fail (GIMP_IS_BRUSH (brush));
  265.  
  266.   brush->spacing = spacing;
  267. }
  268.  
  269. GimpBrush *
  270. gimp_brush_load_brush (gint   fd,
  271.                gchar *filename)
  272. {
  273.   GimpBrush   *brush;
  274.   GPattern    *pattern;
  275.   gint         bn_size;
  276.   BrushHeader  header;
  277.   gchar       *name;
  278.   gint         i;
  279.  
  280.   g_return_val_if_fail (filename != NULL, NULL);
  281.   g_return_val_if_fail (fd != -1, NULL);
  282.  
  283.   /*  Read in the header size  */
  284.   if (read (fd, &header, sizeof (header)) != sizeof (header)) 
  285.     return NULL;
  286.  
  287.   /*  rearrange the bytes in each unsigned int  */
  288.   header.header_size  = g_ntohl (header.header_size);
  289.   header.version      = g_ntohl (header.version);
  290.   header.width        = g_ntohl (header.width);
  291.   header.height       = g_ntohl (header.height);
  292.   header.bytes        = g_ntohl (header.bytes);
  293.   header.magic_number = g_ntohl (header.magic_number);
  294.   header.spacing      = g_ntohl (header.spacing);
  295.  
  296.   /*  Check for correct file format */
  297.   /*  It looks as if version 1 did not have the same magic number.  (neo)  */
  298.   if (header.version != 1 &&
  299.       (header.magic_number != GBRUSH_MAGIC || header.version != 2))
  300.     {
  301.       g_message (_("Unknown brush format version #%d in \"%s\"."),
  302.          header.version, filename);
  303.       return NULL;
  304.     }
  305.  
  306.   if (header.version == 1)
  307.     {
  308.       /*  If this is a version 1 brush, set the fp back 8 bytes  */
  309.       lseek (fd, -8, SEEK_CUR);
  310.       header.header_size += 8;
  311.       /*  spacing is not defined in version 1  */
  312.       header.spacing = 25;
  313.     }
  314.   
  315.    /*  Read in the brush name  */
  316.   if ((bn_size = (header.header_size - sizeof (header))))
  317.     {
  318.       name = g_new (gchar, bn_size);
  319.       if ((read (fd, name, bn_size)) < bn_size)
  320.     {
  321.       g_message (_("Error in GIMP brush file \"%s\"."), filename);
  322.       g_free (name);
  323.       return NULL;
  324.     }
  325.     }
  326.   else
  327.     {
  328.       name = g_strdup (_("Unnamed"));
  329.     }
  330.  
  331.   switch (header.bytes)
  332.     {
  333.     case 1:
  334.       brush = GIMP_BRUSH (gtk_type_new (gimp_brush_get_type ()));
  335.       brush->mask = temp_buf_new (header.width, header.height, 1,
  336.                   0, 0, NULL);
  337.       if (read (fd, 
  338.         temp_buf_data (brush->mask), header.width * header.height) <
  339.       header.width * header.height)
  340.     {
  341.       g_message (_("GIMP brush file appears to be truncated: \"%s\"."),
  342.              filename);
  343.       g_free (name);
  344.       gtk_object_unref (GTK_OBJECT (brush));
  345.       return NULL;
  346.     }
  347.       
  348.       /*  For backwards-compatibility, check if a pattern follows.
  349.       The obsolete .gpb format did it this way.  */
  350.       pattern = pattern_load (fd, filename);
  351.       
  352.       if (pattern)
  353.     {
  354.       if (pattern->mask && pattern->mask->bytes == 3)
  355.         {
  356.           brush->pixmap = pattern->mask;
  357.           pattern->mask = NULL;
  358.         }
  359.       pattern_free (pattern);
  360.     }
  361.       else
  362.     {
  363.       /*  rewind to make brush pipe loader happy  */
  364.       if (lseek (fd, - ((off_t) sizeof (PatternHeader)), SEEK_CUR) < 0)
  365.         {
  366.           g_message (_("GIMP brush file appears to be corrupted: \"%s\"."),
  367.              filename);
  368.           g_free (name);
  369.           gtk_object_unref (GTK_OBJECT (brush));
  370.           return NULL;
  371.         }
  372.     }
  373.       break;
  374.  
  375.     case 4:
  376.       brush = GIMP_BRUSH (gtk_type_new (gimp_brush_get_type ()));
  377.       brush->mask =   temp_buf_new (header.width, header.height, 1, 0, 0, NULL);
  378.       brush->pixmap = temp_buf_new (header.width, header.height, 3, 0, 0, NULL);
  379.  
  380.       for (i = 0; i < header.width * header.height; i++)
  381.     {
  382.       if (read (fd, temp_buf_data (brush->pixmap) 
  383.             + i * 3, 3) != 3 ||
  384.           read (fd, temp_buf_data (brush->mask) + i, 1) != 1)
  385.         {
  386.           g_message (_("GIMP brush file appears to be truncated: \"%s\"."),
  387.              filename);
  388.           g_free (name);
  389.           gtk_object_unref (GTK_OBJECT (brush));
  390.           return NULL;
  391.         }
  392.     }
  393.       break;
  394.       
  395.     default:
  396.       g_message ("Unsupported brush depth: %d\n in file \"%s\"\nGIMP Brushes must be GRAY or RGBA\n",
  397.          header.bytes, filename);
  398.       g_free (name);
  399.       return NULL;
  400.     }
  401.  
  402.   brush->name     = name;
  403.   brush->spacing  = header.spacing;
  404.   brush->x_axis.x = header.width  / 2.0;
  405.   brush->x_axis.y = 0.0;
  406.   brush->y_axis.x = 0.0;
  407.   brush->y_axis.y = header.height / 2.0;
  408.  
  409.   return brush;
  410. }
  411.